<template>
  <h2>Vue3 ref vs reactive 响应式对比 Demo</h2>

  <!-- 计数器部分 -->
  <div style="margin-bottom: 24px">
    <h3>计数器</h3>
    <div>
      <button @click="countRef++">ref 数字加一</button>
      <span style="margin: 0 10px">ref：{{ countRef }}</span>
    </div>
    <div>
      <button @click="countReactive.count++">reactive 数字加一</button>
      <span style="margin: 0 10px">reactive：{{ countReactive.count }}</span>
    </div>
  </div>

  <!-- Todo List 部分 -->
  <div style="margin-bottom: 24px">
    <h3>Todo List 对比</h3>
    <div>
      <strong>reactive 实现：</strong>
      <button @click="addReactiveTodo">新增</button>
      <ul>
        <li v-for="(item, idx) in todosReactive" :key="idx">
          {{ item.text }} - {{ item.done ? "✔" : "❌" }}
          <button @click="item.done = !item.done">切换状态</button>
        </li>
      </ul>
    </div>
    <div>
      <strong>ref 实现：</strong>
      <button @click="addRefTodo">新增</button>
      <ul>
        <li v-for="(item, idx) in todosRef" :key="idx">
          {{ item.text }} - {{ item.done ? "✔" : "❌" }}
          <button @click="item.done = !item.done">切换状态</button>
        </li>
      </ul>
    </div>
  </div>

  <!-- 响应式陷阱与深层对象 -->
  <div>
    <h3>ref 包对象 VS reactive 对象</h3>
    <div>
      <strong>ref 包对象：</strong>
      <input v-model="objRef.name" placeholder="输入名字" />
      <span>objRef.value.name: {{ objRef.name }}</span>
      <button @click="replaceObjRef">整体替换对象</button>
    </div>
    <div>
      <strong>reactive 对象：</strong>
      <input v-model="objReactive.name" placeholder="输入名字" />
      <span>objReactive.name: {{ objReactive.name }}</span>
      <button @click="replaceObjReactive">整体替换对象</button>
    </div>
    <p style="color: gray">
      小提示：ref 包对象时属性本身是响应式的，但如果直接替换 objRef.value =
      新对象，依然能响应。<br />
      reactive 只能响应属性变化，不能直接整体替换对象引用。
    </p>
  </div>
</template>

<script setup>
import { ref, reactive } from "vue";

// 1. 计数器：ref vs reactive
const countRef = ref(0); // 推荐用于基本类型
const countReactive = reactive({ count: 0 }); // 推荐用于复杂对象

// 2. Todo List 对比
const todosReactive = reactive([
  { text: "学习 ref", done: false },
  { text: "学习 reactive", done: false },
]);
function addReactiveTodo() {
  todosReactive.push({ text: "reactive 新任务", done: false });
}

const todosRef = ref([{ text: "ref 新建", done: false }]);
function addRefTodo() {
  // ref 包数组，直接 push 也能响应
  //   todosRef.value.push({ text: "ref 新任务", done: false });
  todosRef.value = [...todosRef.value, { text: "replace 新任务", done: false }];
}

// 3. ref 包对象 VS reactive 对象
const objRef = ref({ name: "ref 对象", age: 18 });
const objReactive = reactive({ name: "reactive 对象", age: 18 });

function replaceObjRef() {
  // 替换整个对象，视图依然会更新
  objRef.value = { name: "ref 已替换", age: 0 };
}

function replaceObjReactive() {
  // 替换无效，视图不会自动响应，建议只修改属性
  objReactive.name = "reactive 手动改名"; // 推荐这样操作
  //   objReactive = { name: "reactive 已替换", age: 0 }; // 这样不会触发响应式
}
</script>
